package cn.yto.print.controller;

import cn.hutool.json.JSONUtil;
import cn.yto.print.config.CustomWindowEvent;
import cn.yto.print.config.ThreadPoolManager;
import cn.yto.print.config.WeightLinkedContext;
import cn.yto.print.config.i18n.LocaleChangeEvent;
import cn.yto.print.constants.AssistantConstants;
import cn.yto.print.exception.BluetoothCommException;
import cn.yto.print.model.response.WeightResponse;
import cn.yto.print.service.BluetoothWeightService;
import cn.yto.print.socket.WeightSocketEndpoint;
import cn.yto.print.utils.CommonUtil;
import de.felixroske.jfxsupport.FXMLController;
import de.felixroske.jfxsupport.GUIState;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.event.EventListener;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


@Slf4j
@FXMLController
public class BluetoothController extends BaseController implements Initializable {

    private static ScheduledExecutorService executor;
    private final SimpleStringProperty displayWeight = new SimpleStringProperty("0");

    @FXML
    public Label weightModel;
    @FXML
    public Label weightLabel;
    @FXML
    public Label wmsConnect;
    @FXML
    public Label wmsStatus;
    @FXML
    public Label runDeviceStatus;
    @FXML
    public Label bluetoothStatus;
    @FXML
    public Label currentDevice;
    @FXML
    public Label bluetoothName;
    @FXML
    public Label runPortTitle;
    @FXML
    public Label runPortLabel;
    @FXML
    public AnchorPane maskCover;
    @FXML
    public Label coverText;

    @Value("${server.port}")
    private String serverPort;
    @Autowired
    private BluetoothWeightService bluetoothService;
    @Autowired
    private WeightSocketEndpoint weightSocketEndpoint;

    private long lastEventTime;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        weightModel.textProperty().bind(I18N.getStringBinding("weight.bluetooth.title"));
        wmsConnect.textProperty().bind(I18N.getStringBinding("weight.wms.linked"));
        runDeviceStatus.textProperty().bind(I18N.getStringBinding("weight.device.status"));
        currentDevice.textProperty().bind(I18N.getStringBinding("weight.current.device"));
        runPortTitle.textProperty().bind(I18N.getStringBinding("weight.runport.title"));
        coverText.textProperty().bind(I18N.getStringBinding("weight.model.cover"));
        // 初始化运行端口和重量显示
        runPortLabel.setText(serverPort);
        weightLabel.textProperty().bind(displayWeight);
    }

    @PostConstruct
    private void addEventListener() {
        Platform.runLater(() -> {
            GUIState.getStage().addEventHandler(CustomWindowEvent.BLUETOOTH_SHOW, event -> {
                Runnable job = this::connectAndRead;
                new Thread(job, "Bluetooth-Connect-Thread").start();
            });
            GUIState.getStage().addEventHandler(CustomWindowEvent.CLOSE_SHOW, event -> {
                this.releaseResources();
            });
        });
    }

    private void connectAndRead() {
        maskCover.setVisible(true);
        releaseResources();
        Platform.runLater(() -> {
            displayWeight.set("0.00");
            bluetoothStatus.setText(I18N.get("weight.connect.linking"));
            updateConnectStyle(wmsStatus, AssistantConstants.DISCONNECT);
        });
        this.startConnectMonitor();
        this.startBluetoothRead();
    }

    private void startConnectMonitor() {
        log.info("启动蓝牙监控线程，正在检测称重服务连接状态 ...");
        if (executor == null || executor.isShutdown()) {
            executor = ThreadPoolManager.getSingleScheduledExecutor();
        }
        executor.scheduleWithFixedDelay(() -> {
            updateConnectStyle(wmsStatus, WeightLinkedContext.getWmsConnectStatus());
            boolean noData = (lastEventTime == 0L) || (System.currentTimeMillis() - lastEventTime > 3000L);
            if (noData) {
                // 推送断开信息
                WeightResponse weightResponse = new WeightResponse(3, "电子秤连接断开");
                weightSocketEndpoint.massMessage(JSONUtil.toJsonStr(weightResponse));
                if (WeightLinkedContext.getDeviceConnectStatus() == 1) {
                    WeightLinkedContext.setDeviceConnectStatus(AssistantConstants.DISCONNECT);
                    Platform.runLater(() -> {
                        displayWeight.set("0.00");
                        bluetoothStatus.setText(I18N.get("weight.connect.unlink"));
                    });
                }
            }
        }, 5, 3, TimeUnit.SECONDS);
    }

    /**
     * 启动蓝牙读取
     */
    private void startBluetoothRead() {
        try {
            bluetoothService.readWeight(weight -> {
                lastEventTime = System.currentTimeMillis();
                if (!displayWeight.getValue().equals(weight)) {
                    Platform.runLater(() -> displayWeight.set(weight));
                }
                if (WeightLinkedContext.getDeviceConnectStatus() != 1) {
                    WeightLinkedContext.setDeviceConnectStatus(AssistantConstants.CONNECTED);
                    Platform.runLater(() -> {
                        bluetoothStatus.setText(I18N.get("weight.connect.open"));
                        bluetoothName.setText(bluetoothService.getBluetoothName());
                    });
                }
            });
        } catch (Exception ex) {
            String message = (ex instanceof BluetoothCommException)
                    ? I18N.get("weight.bluetooth.conn")
                    : I18N.get("weight.bluetooth.error");
            if (!(ex instanceof BluetoothCommException)) {
                log.error("连接蓝牙设备并读取数据发生异常", ex);
            }
            Platform.runLater(() -> {
                bluetoothStatus.setText(I18N.get("weight.connect.failed"));
                bluetoothName.setText(I18N.get("weight.bluetooth.none"));
                showAlert(message);
            });
        } finally {
            maskCover.setVisible(false);
        }
    }

    @EventListener
    public void updateLocaleEvent(LocaleChangeEvent event) {
        if (wmsStatus != null) {
            Platform.runLater(() ->
                    updateConnectStyle(wmsStatus, WeightLinkedContext.getWmsConnectStatus())
            );
        }
    }

    private void releaseResources() {
        bluetoothService.closeBluetooth();
        // 重置设备连接状态
        WeightLinkedContext.resetDeviceConnect();
    }

    private void updateConnectStyle(Label label, Integer status) {
        Platform.runLater(() -> {
            boolean linked = (status != null && status == 1);
            label.setText(linked ? I18N.get("weight.connect.linked") : I18N.get("weight.connect.unlink"));
            label.getStyleClass().setAll(linked ? "label-green" : "label-red");
        });
    }

}

